/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package dao;

import java.util.List;
import javax.persistence.EntityExistsException;
import javax.persistence.EntityManager;
import javax.persistence.TypedQuery;
import util.Mensagem;
import util.Reflexao;

public class GenericDAO<T> implements InterfaceDAO<T> {

    private final EntityManager em;

    public EntityManager getEm() {
        return em;
    }

    public GenericDAO() {
        this.em = (EntityManager) FabricaEntityManager.obterFabrica().createEntityManager();
    }

    public boolean iniciarTransacao() {
        try {
            if (em.getTransaction().isActive()) {
                return true;
            }
            em.getTransaction().begin();
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    public boolean confirmarTransacao() {
        try {
            em.getTransaction().commit();
            return true;
        } catch (EntityExistsException e) {
            return false;
        }
    }

    public boolean desfazerTransacao() {
        try {
            em.getTransaction().rollback();
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    @Override
    public void criar(T entidade) {
        try {
            Object id = Reflexao.obterId(entidade);
            this.iniciarTransacao();
            if (id == null) {
                em.persist(entidade);
                this.confirmarTransacao();
                Mensagem.setMensagemOperacao("Salvo com Sucesso!");
            } else {
                em.merge(entidade);
                this.confirmarTransacao();
                Mensagem.setMensagemOperacao("Alterações Salvas com Sucesso!");
            }

        } catch (Exception e) {
            Mensagem.setMensagemOperacao("Erro ao Salvar!");
            if (em.isOpen()) {
                this.desfazerTransacao();
            }

        }
    }

    @Override
    public boolean excluir(T o) {
        try {
            this.iniciarTransacao();
            em.remove(em.merge(o));
            this.confirmarTransacao();
            return true;
        } catch (Exception e) {
            if (em.isOpen()) {
                this.desfazerTransacao();
            }
            return false;
        }
    }


    @Override
    public T obter(Class<T> classe, Object id) {
        try {
            String namedQuery = classe.getSimpleName() + ".findById";
            TypedQuery<T> q = em.createNamedQuery(namedQuery, classe);
            q.setParameter("id", id);
            T o = q.getSingleResult();
            return o;
        } catch (Exception e) {
            
            return null;
        }
    }

    @Override
    public List<T> obterTodos(Class<T> classe) {
        try {
            String query = classe.getSimpleName() + ".findAll";
        TypedQuery<T> q = em.createNamedQuery(query, classe);
        return q.getResultList();
        } catch (Exception e) {
            return null;
        }
    }

    public EntityManager getEntityManager() {
        return em;
    }

    @Override
    protected void finalize() throws Throwable {
        try {
             super.finalize();
        if (this.em != null && this.em.isOpen()) {
            this.em.close();
        }
        } catch (Exception e) {
            System.out.println("Erro finalize DAO: "+e.getMessage());
        }
    }
}
